package tasknow.parser;

import java.util.Arrays;
import java.util.Calendar;
import java.util.Vector;

import tasknow.utils.Constants;

public class Parser {

	//@author A0096638M

	// Converter

	// String to Calendar

	public static Calendar parseToFullCalendarFormat(String dateTime) {
		Calendar newCalendar = Calendar.getInstance();

		if (dateTime.length() == Constants.LENGTH_DATE_TIME_FORMAT) {
			String[] dateTimeArray = dateTime.split(Constants.BLANK_SPACE);
			int[] date = parseDate(dateTimeArray[Constants.DATE]);
			int[] time = parseTime(dateTimeArray[Constants.TIME]);

			newCalendar.set(date[Constants.YEAR], date[Constants.MONTH],
					date[Constants.DAY], time[Constants.HOUR],
					time[Constants.MINUTE]);
		} else if (dateTime.length() == Constants.LENGTH_DATE_FORMAT) {
			int[] date = parseDate(dateTime);

			newCalendar.set(date[Constants.YEAR], date[Constants.MONTH],
					date[Constants.DAY]);
			newCalendar.set(Calendar.HOUR_OF_DAY, Constants.ZEROTH);
			newCalendar.clear(Calendar.MINUTE);
			newCalendar.clear(Calendar.SECOND);
			newCalendar.clear(Calendar.MILLISECOND);
		}

		return newCalendar;
	}

	// String date to integer[] date

	public static int[] parseDate(String date) {
		int[] dateInt = new int[Constants.SIZE_THREE_ARRAY];

		dateInt[Constants.YEAR] = Integer.parseInt(date.substring(
				Constants.INDEX_YEAR_SUBSTRING_START,
				Constants.INDEX_YEAR_SUBSTRING_END))
				+ Constants.TWENTY_FIRST_CENTURY;
		dateInt[Constants.MONTH] = Integer.parseInt(date.substring(
				Constants.INDEX_MONTH_SUBSTRING_START,
				Constants.INDEX_MONTH_SUBSTRING_END));
		dateInt[Constants.DAY] = Integer.parseInt(date.substring(
				Constants.INDEX_DAY_SUBSTRING_START,
				Constants.INDEX_DAY_SUBSTRING_END));

		return dateInt;
	}

	// String date to integer[] date

	public static int[] parseTime(String time) {
		int[] timeInt = new int[Constants.SIZE_TWO_ARRAY];

		timeInt[Constants.HOUR] = Integer.parseInt(time.substring(
				Constants.INDEX_HOUR_SUBSTRING_START,
				Constants.INDEX_HOUR_SUBSTRING_END));
		timeInt[Constants.MINUTE] = Integer.parseInt(time.substring(
				Constants.INDEX_MINUTE_SUBSTRING_START,
				Constants.INDEX_MINUTE_SUBSTRING_END));

		return timeInt;
	}

	public static String parseDateString(Calendar cal) {
		return String.format(Constants.FORMAT_DATE_STRING_NO_SLASH,
				cal.get(Calendar.DATE), cal.get(Calendar.MONTH),
				cal.get(Calendar.YEAR));
	}

	// Understands the type of command input by user

	public static Constants.COMMANDS parseCommandType(String userCommand) {
		String commandTypeString = userCommand;

		if (commandTypeString == null) {
			throw new Error(Constants.ERROR_NULL_COMMAND_INPUT);
		}

		try {
			Constants.COMMANDS command = Constants.COMMANDS
					.valueOf(commandTypeString.trim().toUpperCase());

			return command;
		} catch (IllegalArgumentException ex) {
			return Constants.COMMANDS.INVALID;
		}
	}

	// Understands the day input by user

	public static int parseDayOfWeek(String day) {
		day.toLowerCase();

		switch (day) {
			case "monday":
				return Calendar.MONDAY;
	
			case "mon":
				return Calendar.MONDAY;
	
			case "tuesday":
				return Calendar.TUESDAY;
	
			case "tue":
				return Calendar.TUESDAY;
	
			case "tues":
				return Calendar.TUESDAY;
	
			case "wednesday":
				return Calendar.WEDNESDAY;
	
			case "wed":
				return Calendar.WEDNESDAY;
	
			case "thurday":
				return Calendar.THURSDAY;
	
			case "thu":
				return Calendar.THURSDAY;
	
			case "thur":
				return Calendar.THURSDAY;
	
			case "thurs":
				return Calendar.THURSDAY;
	
			case "friday":
				return Calendar.FRIDAY;
	
			case "fri":
				return Calendar.FRIDAY;
	
			case "saturday":
				return Calendar.SATURDAY;
	
			case "sat":
				return Calendar.SATURDAY;
	
			case "sunday":
				return Calendar.SUNDAY;
	
			case "sun":
				return Calendar.SUNDAY;
	
			default:
				throw new Error (String.format(Constants.ERROR_INVALID_ARGUMENT_DETECTED, day));
		}
	}

	// Converts a vector of date and/or time into calendar object

	public static Calendar[] parseToCalendar(Vector<String> vector) {
		int[] numberOfDateAndTimeArgs = determineNumberOfTimeAndDateArgs(vector);

		if (numberOfDateAndTimeArgs[Constants.INDEX_DATE_ARGS] == Constants.ZEROTH) {
			String date = getTodayDate();

			if (numberOfDateAndTimeArgs[Constants.INDEX_TIME_ARGS] == Constants.ZEROTH) {
				Calendar start = null;
				Calendar end = null;

				return formCalendarArray(start, end);
			} else if (numberOfDateAndTimeArgs[Constants.INDEX_TIME_ARGS] == Constants.FIRST) {
				Calendar start = Parser.parseToFullCalendarFormat(date);
				String endDateString = String.format(
						Constants.CONCANTENATE_DATE_AND_TIME, date,
						vector.lastElement());
				Calendar end = Parser.parseToFullCalendarFormat(endDateString);

				return formCalendarArray(start, end);
			} else if (numberOfDateAndTimeArgs[Constants.INDEX_TIME_ARGS] == Constants.SECOND) {
				String startDateString = String.format(
						Constants.CONCANTENATE_DATE_AND_TIME, date,
						vector.firstElement());
				Calendar start = Parser
						.parseToFullCalendarFormat(startDateString);
				String endDateString = String.format(
						Constants.CONCANTENATE_DATE_AND_TIME, date,
						vector.lastElement());
				Calendar end = Parser.parseToFullCalendarFormat(endDateString);

				return formCalendarArray(start, end);
			}
		} else if (numberOfDateAndTimeArgs[Constants.INDEX_DATE_ARGS] == Constants.FIRST) {
			if (numberOfDateAndTimeArgs[Constants.INDEX_TIME_ARGS] == Constants.ZEROTH) {
				Calendar start = null;
				String endDateString = vector.lastElement();
				Calendar end = Parser.parseToFullCalendarFormat(endDateString);

				return formCalendarArray(start, end);
			} else if (numberOfDateAndTimeArgs[Constants.INDEX_TIME_ARGS] == Constants.FIRST) {
				String endDateTime = getAndConcantenateFirstTwoElements(vector);
				Calendar end = Parser.parseToFullCalendarFormat(endDateTime);
				Calendar start = null;

				return formCalendarArray(start, end);
			} else if (numberOfDateAndTimeArgs[Constants.INDEX_TIME_ARGS] == Constants.SECOND) {
				String date = vector.firstElement();
				vector = removeDate(vector);
				String startDateString = String.format(
						Constants.CONCANTENATE_DATE_AND_TIME, date,
						vector.firstElement());
				Calendar start = Parser
						.parseToFullCalendarFormat(startDateString);
				String endDateString = String.format(
						Constants.CONCANTENATE_DATE_AND_TIME, date,
						vector.lastElement());
				Calendar end = Parser.parseToFullCalendarFormat(endDateString);

				return formCalendarArray(start, end);
			}
		} else if (numberOfDateAndTimeArgs[Constants.INDEX_DATE_ARGS] == Constants.SECOND) {
			if (numberOfDateAndTimeArgs[Constants.INDEX_TIME_ARGS] == Constants.ZEROTH) {
				String startDateString = vector.firstElement();
				String endDateString = vector.lastElement();
				Calendar start = Parser
						.parseToFullCalendarFormat(startDateString);
				Calendar end = Parser.parseToFullCalendarFormat(endDateString);

				return formCalendarArray(start, end);
			} else if (numberOfDateAndTimeArgs[Constants.INDEX_TIME_ARGS] == Constants.FIRST) {
				String startDateString = vector.firstElement();
				Calendar start = Parser
						.parseToFullCalendarFormat(startDateString);
				vector = removeStartDateTime(vector);
				String endDateTime = getAndConcantenateFirstTwoElements(vector);
				Calendar end = Parser.parseToFullCalendarFormat(endDateTime);

				return formCalendarArray(start, end);
			} else if (numberOfDateAndTimeArgs[Constants.INDEX_TIME_ARGS] == Constants.SECOND) {
				String startDateTime = getAndConcantenateFirstTwoElements(vector);
				Calendar start = Parser
						.parseToFullCalendarFormat(startDateTime);
				vector = removeStartDateTime(vector);
				String endDateTime = getAndConcantenateFirstTwoElements(vector);
				Calendar end = Parser.parseToFullCalendarFormat(endDateTime);

				return formCalendarArray(start, end);
			}
		}

		return formCalendarArray(null, null);
	}

	// Converts any time to 24 hour type

	private static String convertToTwentyFourHours(String time) {
		String hour = getTimeFromAMPM(time);

		if (isAM(time)) {
			return addZeroUntilFourDigits(hour);
		} else if (isPM(time)) {
			hour = addZeroUntilFourDigits(hour);
			return convertHours(hour);
		} else {
			return Constants.EMPTY_STRING;
		}
	}

	private static String convertHours(String time) {
		String hour = Constants.EMPTY_STRING;
		String minute = getMinute(time);

		if (getHour(time).equalsIgnoreCase(Constants.TIME_NOON_HOUR)) {
			hour = getHour(time);
		} else if (getHour(time).equalsIgnoreCase(
				Constants.TIME_MIDNIGHT_HOUR_INPUT)) {
			hour = Constants.TIME_MIDNIGHT_HOUR_ACTUAL;
		} else {
			hour = Integer.toString(Integer.parseInt(getHour(time))
					+ Constants.ADJUST_TWELVE_HOURS);
		}

		return hour + minute;
	}

	// Transforms Strings into correct date/time format

	public static String[] transformToAcceptableArgs(String[] args) {
		Vector<String> inputs = new Vector<String>(
				Arrays.asList(args[Constants.INDEX_INPUT]
						.split(Constants.BLANK_SPACE)));

		for (int i = 0; i < inputs.size(); i++) {
			if (inputs.get(i).isEmpty()) {

			} else if (isToday(inputs.get(i))) {
				inputs.set(i, getTodayDate());
			} else if (isTomorrow(inputs.get(i))) {
				inputs.set(i, getTomorrowDate());
			} else if (isNext(inputs.get(i)) && isDay(inputs.get(i + 1))) {
				inputs.set(i, getNextWeekDay(inputs.get(i + 1)));
				inputs.remove(i + 1);
			} else if (isDay(inputs.get(i))) {
				inputs.set(i, getDay(inputs.get(i)));
			} else if (isAM(inputs.get(i)) || isPM(inputs.get(i))) {
				inputs.set(i, convertToTwentyFourHours(inputs.get(i)));
			} else if (isInteger(inputs.get(i)) && isDateFormat(inputs.get(i))) {
				inputs.set(i, adjustMonth(inputs.get(i)));
			}
		}

		String sentence = Constants.BLANK_SPACE;

		for (int i = 0; i < inputs.size(); i++) {
			sentence += inputs.get(i);
			sentence += Constants.BLANK_SPACE;
		}

		args[Constants.INDEX_INPUT] = sentence.trim();

		return args;
	}

	// Other utilities used by Parser

	// Booleans

	public static boolean isPreposition(String preposition) {
		if (preposition.equalsIgnoreCase(Constants.PREPOSITION_TO)
				|| preposition.equalsIgnoreCase(Constants.PREPOSITION_AT)
				|| preposition.equalsIgnoreCase(Constants.PREPOSITION_FROM)
				|| preposition.equalsIgnoreCase(Constants.PREPOSITION_BY)
				|| preposition.equalsIgnoreCase(Constants.PREPOSITION_ON)
				|| preposition.equalsIgnoreCase(Constants.PREPOSITION_BEFORE)
				|| preposition.equalsIgnoreCase(Constants.SHORTCUT_B4)
				|| preposition.equalsIgnoreCase(Constants.SHORTCUT_AT)) {
			return true;
		}

		return false;
	}

	private static boolean isNext(String word) {
		return word.equalsIgnoreCase(Constants.STRING_NEXT)
				|| word.equalsIgnoreCase(Constants.SHORTCUT_NXT);
	}

	private static boolean isDay(String word) {
		return word.endsWith(Constants.STRING_DAY)
				&& word.length() > Constants.MINIMUM_LENGTH_STRING_DAY
				&& isADay(word) || isDays(word);
	}

	private static boolean isDays(String word) {
		String day = word.toLowerCase();
		
		return day.equalsIgnoreCase(Constants.SHORTCUT_MON)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_TUE)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_TUES)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_WED)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_THU)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_THUR)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_THURS)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_FRI)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_SAT)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_SUN);
	}

	private static boolean isADay(String word) {
		String day = word.toLowerCase();
		
		return day.startsWith(Constants.SHORTCUT_MON)
				|| day.startsWith(Constants.SHORTCUT_TUE)
				|| day.startsWith(Constants.SHORTCUT_TUES)
				|| day.startsWith(Constants.SHORTCUT_WED)
				|| day.startsWith(Constants.SHORTCUT_THU)
				|| day.startsWith(Constants.SHORTCUT_THUR)
				|| day.startsWith(Constants.SHORTCUT_THURS)
				|| day.startsWith(Constants.SHORTCUT_FRI)
				|| day.startsWith(Constants.SHORTCUT_SAT)
				|| day.startsWith(Constants.SHORTCUT_SUN);
	}

	public static boolean isInteger(String s) {
		try {
			Integer.parseInt(s);
		} catch (NumberFormatException nfe) {
			return false;
		}
		return true;
	}

	private static boolean isAM(String time) {
		if (time.toUpperCase().contains(Constants.STRING_AM)) {
			int lengthOfTime = time.length();
			String beforeAM = time.substring(Constants.ZEROTH, lengthOfTime
					- Constants.LENGTH_STRING_AM);
			boolean isTime = isInteger(beforeAM);

			return isTime;
		} else {
			return false;
		}

	}

	private static boolean isPM(String time) {
		if (time.toUpperCase().contains(Constants.STRING_PM)) {
			int lengthOfTime = time.length();
			String beforePM = time.substring(Constants.ZEROTH, lengthOfTime
					- Constants.LENGTH_STRING_PM);
			boolean isTime = isInteger(beforePM);

			return isTime;
		} else {
			return false;
		}
	}

	public static boolean isValidCalendarFormat(String toCheck) {
		if (isTodayOrTomorrow(toCheck)) {
			return isTodayOrTomorrow(toCheck);
		} else if (isInteger(toCheck)) {
			if (isDateLength(toCheck)) {
				return isDateFormat(toCheck);
			} else if (isTimeLength(toCheck)) {
				return isTimeFormat(toCheck);
			} else {
				return false;
			}
		} else {
			return isTwelveHourFormat(toCheck);
		}
	}

	private static boolean isTodayOrTomorrow(String day) {
		return isToday(day) || isTomorrow(day);
	}

	private static boolean isToday(String day) {
		return day.equalsIgnoreCase(Constants.STRING_TODAY)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_TDY)
				|| day.equalsIgnoreCase(Constants.STRING_TONIGHT)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_TO9)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_2NITE)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_2NIGHT)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_2DAY);
	}

	private static boolean isTomorrow(String day) {
		return day.equalsIgnoreCase(Constants.STRING_TOMORROW)
				|| day.equalsIgnoreCase(Constants.SHORTCUT_TMR);
	}

	private static boolean isDateLength(String date) {
		return date.length() == Constants.LENGTH_DATE_FORMAT;
	}

	public static boolean isDateTimeFormat(String dateTime) {
		if (dateTime.length() == Constants.LENGTH_DATE_TIME_FORMAT) {
			String[] temp = dateTime.split(Constants.BLANK_SPACE);
			
			return isInteger(temp[Constants.INDEX_DATE_ARGS]) && isDateFormat(temp[Constants.INDEX_DATE_ARGS]) && isInteger(temp[Constants.INDEX_TIME_ARGS])
					&& isTimeFormat(temp[Constants.INDEX_TIME_ARGS]);
		} else {
			return false;
		}
	}

	public static boolean isDateFormat(String date) {
		return isDateLength(date) && isCorrectDay(date) && isCorrectMonth(date)
				&& isCorrectYear(date);
	}

	private static boolean isCorrectDay(String date) {
		return Integer.parseInt(date.substring(
				Constants.INDEX_DAY_SUBSTRING_START,
				Constants.INDEX_DAY_SUBSTRING_END)) <= Constants.MAX_NUMBER_OF_DAYS
				&& Integer.parseInt(date.substring(
						Constants.INDEX_DAY_SUBSTRING_START,
						Constants.INDEX_DAY_SUBSTRING_END)) >= Constants.MIN_NUMBER_OF_DAYS;
	}

	private static boolean isCorrectMonth(String date) {
		return Integer.parseInt(date.substring(
				Constants.INDEX_MONTH_SUBSTRING_START,
				Constants.INDEX_MONTH_SUBSTRING_END)) <= Constants.MAX_NUMBER_OF_MONTHS
				&& Integer.parseInt(date.substring(
						Constants.INDEX_MONTH_SUBSTRING_START,
						Constants.INDEX_MONTH_SUBSTRING_END)) >= Constants.MIN_NUMBER_OF_MONTHS;
	}

	private static boolean isCorrectYear(String date) {
		return Integer.parseInt(date.substring(
				Constants.INDEX_YEAR_SUBSTRING_START,
				Constants.INDEX_YEAR_SUBSTRING_END)) <= Constants.MAX_NUMBER_OF_YEARS;
	}

	private static boolean isTimeLength(String time) {
		return time.length() == Constants.LENGTH_TIME_FORMAT;
	}

	public static boolean isTimeFormat(String time) {
		return isTimeLength(time) && isCorrectHour(time)
				&& isCorrectMinute(time) && isCorrectTime(time);
	}

	private static boolean isCorrectHour(String time) {
		return Integer.parseInt(time.substring(
				Constants.INDEX_HOUR_SUBSTRING_START,
				Constants.INDEX_HOUR_SUBSTRING_END)) <= Constants.MAX_NUMBER_OF_HOURS;
	}

	private static boolean isCorrectMinute(String time) {
		return Integer.parseInt(time.substring(
				Constants.INDEX_MINUTE_SUBSTRING_START,
				Constants.INDEX_MINUTE_SUBSTRING_END)) <= Constants.MAX_NUMBER_OF_MINUTES;
	}

	private static boolean isCorrectTime(String time) {
		return Integer.parseInt(time) <= Constants.MAX_ALLOWED_TIME;
	}

	private static boolean isTwelveHourFormat(String time) {
		if (isAM(time)) {
			time = getTimeFromAMPM(time);
			if (isInteger(time)) {
				time = Parser.addZeroUntilFourDigits(time);
				
				return checkTwelveHoursFormat(time);
			} else {
				return false;
			}
		} else if (isPM(time)) {
			time = getTimeFromAMPM(time);

			if (isInteger(time)) {
				time = Parser.addZeroUntilFourDigits(time);
				
				return checkTwelveHoursFormat(time);
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	private static boolean checkTwelveHoursFormat(String time) {
		return Integer.parseInt(time.substring(
				Constants.INDEX_HOUR_SUBSTRING_START,
				Constants.INDEX_HOUR_SUBSTRING_END)) <= Constants.MAX_NUMBER_OF_TWELVE_HOURS
				&& Integer.parseInt(time.substring(
						Constants.INDEX_MINUTE_SUBSTRING_START,
						Constants.INDEX_MINUTE_SUBSTRING_END)) <= Constants.MAX_NUMBER_OF_MINUTES;
	}

	// Extractors

	private static String getAndConcantenateFirstTwoElements(
			Vector<String> vector) {
		String date = vector.firstElement();
		vector.remove(vector.firstElement());
		String time = vector.firstElement();

		return String.format(Constants.CONCANTENATE_DATE_AND_TIME, date, time);
	}

	private static String getHour(String time) {
		return time.substring(Constants.INDEX_HOUR_SUBSTRING_START,
				Constants.INDEX_HOUR_SUBSTRING_END);
	}

	private static String getMinute(String time) {
		return time.substring(Constants.INDEX_MINUTE_SUBSTRING_START,
				Constants.INDEX_MINUTE_SUBSTRING_END);
	}

	private static String getTimeFromAMPM(String time) {
		int indexBeforeAMPM = getIndexBeforeAMPM(time);

		return time.substring(Constants.INDEX_SUBSTRING_FIRST, indexBeforeAMPM);
	}

	private static int getIndexBeforeAMPM(String time) {
		return time.length() - Constants.ADJUST_INDEX_BY_2;
	}

	// Getters

	public static String getTodayDate() {
		Calendar cal = Calendar.getInstance();
		String day = String.format(Constants.FORMAT_DATE_COMPONENT,
				cal.get(Calendar.DAY_OF_MONTH));
		String month = String.format(Constants.FORMAT_DATE_COMPONENT,
				cal.get(Calendar.MONTH));
		String year = String.format(Constants.FORMAT_DATE_COMPONENT,
				cal.get(Calendar.YEAR) - Constants.TWENTY_FIRST_CENTURY);

		return day + month + year;
	}

	private static String getTomorrowDate() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DAY_OF_YEAR, Constants.TOMORROW);
		String day = String.format(Constants.FORMAT_DATE_COMPONENT,
				cal.get(Calendar.DAY_OF_MONTH));
		String month = String.format(Constants.FORMAT_DATE_COMPONENT,
				cal.get(Calendar.MONTH));
		String year = String.format(Constants.FORMAT_DATE_COMPONENT,
				cal.get(Calendar.YEAR) - Constants.TWENTY_FIRST_CENTURY);

		return day + month + year;
	}

	private static String getNextWeekDay(String day) {
		int dayOfWeek = parseDayOfWeek(day);
		Calendar now = Calendar.getInstance();

		while (now.get(Calendar.DAY_OF_WEEK) != dayOfWeek) {
			now.add(Calendar.DATE, Constants.ONE_DAY);
		}

		now.add(Calendar.DATE, Constants.DAYS_IN_ONE_WEEK);

		String date = String.format(Constants.FORMAT_DATE_COMPONENT,
				now.get(Calendar.DAY_OF_MONTH));
		String month = String.format(Constants.FORMAT_DATE_COMPONENT,
				now.get(Calendar.MONTH));
		String year = String.format(Constants.FORMAT_DATE_COMPONENT,
				now.get(Calendar.YEAR) - Constants.TWENTY_FIRST_CENTURY);

		return date + month + year;
	}

	private static String getDay(String day) {
		int dayOfWeek = parseDayOfWeek(day);
		Calendar now = Calendar.getInstance();

		while (now.get(Calendar.DAY_OF_WEEK) != dayOfWeek) {
			now.add(Calendar.DATE, Constants.ONE_DAY);
		}

		String date = String.format(Constants.FORMAT_DATE_COMPONENT,
				now.get(Calendar.DAY_OF_MONTH));
		String month = String.format(Constants.FORMAT_DATE_COMPONENT,
				now.get(Calendar.MONTH));
		String year = String.format(Constants.FORMAT_DATE_COMPONENT,
				now.get(Calendar.YEAR) - Constants.TWENTY_FIRST_CENTURY);

		return date + month + year;
	}

	// Adders

	public static String addZeroUntilFourDigits(String time) {
		if (time.length() <= Constants.LENGTH_HOUR_ONLY) {
			time = addTwoZeroBehind(time);
		}

		if (time.length() == Constants.LENGTH_ONE_HOUR_DIGIT_WITH_MINUTES) {
			return addOneZeroInFront(time);
		} else {
			return time;
		}
	}

	private static String addTwoZeroBehind(String time) {
		return time + Constants.STRING_ZERO + Constants.STRING_ZERO;
	}

	private static String addOneZeroInFront(String time) {
		return Constants.STRING_ZERO + time;
	}

	// Removers

	private static Vector<String> removeStartDateTime(Vector<String> vector) {
		while (vector.size() != Constants.SIZE_ONE_DATE_TIME) {
			vector.remove(vector.firstElement());
		}

		return vector;
	}

	private static Vector<String> removeDate(Vector<String> vector) {
		vector.remove(Constants.INDEX_ONE_DATE_ARRAY);

		return vector;
	}

	// Miscellaneous

	private static Calendar[] formCalendarArray(Calendar start, Calendar end) {
		return new Calendar[] { start, end };
	}

	private static String adjustMonth(String date) {
		assert (isInteger(date));

		int[] dateInt = parseDate(date);
		String day = String.format(Constants.FORMAT_DATE_COMPONENT,
				dateInt[Constants.DAY]);
		String month = String.format(Constants.FORMAT_DATE_COMPONENT,
				dateInt[Constants.MONTH] - Constants.ADJUST_MONTH_BY_ONE);
		String year = String.format(Constants.FORMAT_DATE_COMPONENT,
				dateInt[Constants.YEAR] - Constants.TWENTY_FIRST_CENTURY);

		return day + month + year;
	}

	private static int[] determineNumberOfTimeAndDateArgs(Vector<String> vector) {
		int[] numberOfTimeAndDateArgs = new int[Constants.SIZE_TWO_ARRAY];

		for (int i = 0; i < vector.size(); i++) {
			if (isTimeFormat(vector.get(i))) {
				numberOfTimeAndDateArgs[Constants.INDEX_TIME_ARGS]++;
			} else if (isDateFormat(vector.get(i))) {
				numberOfTimeAndDateArgs[Constants.INDEX_DATE_ARGS]++;
			}
		}

		return numberOfTimeAndDateArgs;
	}
}
